﻿//Copyright (c) 2009-2010, Andreas Grünwald
//All rights reserved.

using System;
using System.Collections.ObjectModel;

#if !SILVERLIGHT   
using yaTDL.Core.Properties;
using System.Diagnostics;
#endif

namespace yaTDL.Core
{
    /// <summary>
    /// Represents a single Task in a to-do list.
    /// </summary>
    public class Task: ObjectWithId
    {
        
        #region Fields

        private string _content;
        private bool _completed;
        private DateTime _dueDate;
        private int _priority;
        private string _projectId;
        private Recurrence recurrence = new Recurrence();

        #endregion

        #region Properties

        /// <summary>
        /// The Content of the Task
        /// </summary>
        public string Content
        {
            get { return _content; }
            set
            {
                if (value != _content)
                {
                    _content = value;
                    RaisePropertyChanged("Content");
                }
            }
        }

        /// <summary>
        /// Indicates whether the Task has been completed or not.
        /// </summary>
        public bool Completed
        {
            get { return _completed; }
            set
            {
                if (Recurrence.IsRepeating && value == true)
                {
                    //if the Task is repeating, it is moved forward to the next date
                    //a completed copy of the Task will be added (has new id)

                    Task archivedCopy = new Task();
                    archivedCopy.ApplyProperties(this);
                    archivedCopy.Completed = true;

                    TaskStore.AddTask(archivedCopy);

                    this.DueDate = Recurrence.GetNextDate(DueDate);

                }
                else
                {
                    if (value != _completed)
                    {
                        _completed = value;
                        RaisePropertyChanged("InHistory");  //keep in here for backwards compatibility
                        RaisePropertyChanged("Completed");
                    }
                }

            }
        }

        /// <summary>
        /// The DateTime that indicates when the Task becomes due.
        /// </summary>
        public DateTime DueDate
        {
            get { return _dueDate; }
            set
            {
                if (value != _dueDate)
                {                    
                    _dueDate = value;
                    RaisePropertyChanged("DueDate");
                }
            }
        }

        /// <summary>
        /// The priority of the Task.
        /// </summary>
        public int Priority
        {
            get
            {
                return _priority;
            }
            set
            {
                if (value > 3) value = 0;
                
                if (value != _priority)
                {                    
                    _priority = value;
                    RaisePropertyChanged("Priority");
                }
            }
        }

        /// <summary>
        /// The Id of the Project that contains the Task (should be empty when the Task does not belong to a Project)
        /// </summary>
        public string ProjectId
        {
            get { return _projectId; }
            set
            {
                if (value != _projectId)
                {
                    _projectId = value;
                    RaisePropertyChanged("ProjectId");
                }
            }
        }

        public Recurrence Recurrence 
        { 
            get { return recurrence; } 
            set { recurrence = value; } 
        }

        

        #endregion


        #region Constructor(s)
        
        /// <summary>
        /// Initializes a new instance of Task.
        /// </summary>
        [DebuggerStepThrough()]
        public Task()
            : base("l_t_")
        {
            Priority = 0;       //sets the Priotity propertx to its default value
            recurrence.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(recurrence_PropertyChanged);

            ApplicationEvents.DateChanged += new EventHandler(ApplicationEvents_DateChanged);   
        }      
        
        #endregion


        #region Private Methods

        //Admittedly ugly workaround. In the view, there might be displayed 'tomorrow', 'today' instead of the real date. 
        //To make sure this is always shown correctly, it will raise a PropertyChanged event for DueDate although the its value hasn't actually changed.
        private void ApplicationEvents_DateChanged(object sender, EventArgs e)
        {
            RaisePropertyChanged("DueDate");
        }


        /// <summary>
        /// Handles the PropertyChanged event of the Task's Recurrence and raises a PropertyChanged event in Task.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>        
        private void recurrence_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            RaisePropertyChanged("Recurrence");
        }

        #endregion

        #region Public Methods
        
        public Collection<PropertyChange> Diff(Task otherTask)
        {
            Collection<PropertyChange> result = base.Diff(otherTask);
           
            if (this.Content != otherTask.Content)
            { result.Add(new PropertyChange() { PropertyName = "Content", Value1 = this.Content, Value2 = otherTask.Content }); }

            if (this.DueDate != otherTask.DueDate)
            { result.Add(new PropertyChange() { PropertyName = "DueDate", Value1 = this.DueDate, Value2 = otherTask.DueDate }); }

            if (this.Completed != otherTask.Completed)
            { result.Add(new PropertyChange() { PropertyName = "InHistory", Value1 = this.Completed, Value2 = otherTask.Completed }); }
         
            if (this.Priority != otherTask.Priority)
            { result.Add(new PropertyChange() { PropertyName = "Priority", Value1 = this.Priority, Value2 = otherTask.Priority }); }

            if (this.ProjectId != otherTask.ProjectId)
            { result.Add(new PropertyChange() { PropertyName = "ProjectId", Value1 = this.ProjectId, Value2 = otherTask.ProjectId }); }
         
            if (this.Recurrence.Repeat != otherTask.Recurrence.Repeat || this.Recurrence.AdvancedRepeat != otherTask.Recurrence.AdvancedRepeat)
            { result.Add(new PropertyChange() { PropertyName = "Recurrence", Value1 = this.Recurrence, Value2 = otherTask.Recurrence }); }


            return result;
        }

        public void ApplyProperties(Task otherTask)
        {
            this.Collapsed = otherTask.Collapsed;
            this.Content = otherTask.Content;
            this.DueDate = otherTask.DueDate;
            this.Indent = otherTask.Indent;
            this.Completed = otherTask.Completed;
            this.Order = otherTask.Order;
            this.Priority = otherTask.Priority;
            this.ProjectId = otherTask.ProjectId;
            this.Recurrence.AdvancedRepeat = otherTask.Recurrence.AdvancedRepeat;
            this.Recurrence.Repeat = otherTask.Recurrence.Repeat;
            this.UserId = otherTask.UserId;
        }

        [DebuggerStepThrough()]
        public override string ToString()
        {
            string result = "Task - ";
            result += "Content: " + Content + " - ";
            result += "InHistory: " + Completed.ToString() + " - ";
            result += "DueDate: " + DueDate.ToString() + " - ";
            result += "Priority: " + Priority.ToString() + " - ";
            result += "ProjectId: " + ProjectId + " - ";
            result += base.ToString();

            return result;
        }

        [DebuggerStepThrough()]
        public string ToShortString()
        {
            return String.Format("Task: {0}, Id: {1}, InHistory: {2}", this.Content, this.Id, this.Completed);
        }

        #endregion
    }
}
